<?php

namespace App\Services;

use App\Common\Libs\IdBuilder;
use App\Consts\DingTalkConst;
use App\Consts\ExceptionCodeConst;
use App\Consts\MessageConfigConst;
use App\Consts\MessageConst;
use App\Consts\SmsConst;

/**
 * 消息场景服务
 * Class SceneService
 * @package App\Services
 */
class MsgSceneService extends BaseService
{

    /**
     * MsgSceneService constructor.
     */
    public function __construct()
    {
        parent::__construct();
        $this->repository = repository()->MsgSceneRepository;
    }

    /**
     * get scene info
     * @param $params
     * @return array|mixed
     */
    public function getSceneInfo($params)
    {
        if (is_numeric($params)) {
            $id = intval($params);
            $info = $this->repository->getInfoById($id);
        } elseif (is_array($params)) {
            $info = $this->repository->getInfoByWhere($params);
        } else {
            $info = [];
        }
        if (empty($info)) {
            return $this->error(lang('Empty Record'), '80221', $params);
        }
        $info = $this->getExtFields($info, true);
        return $info;
    }

    /**
     * 获取场景列表
     * @return array
     */
    public function getSceneList()
    {
        return $this->repository->getList();
    }

    /**
     * 获取具体场景列表
     * @param $params
     * @return array
     */
    public function getDetailList($params)
    {
        $type = getVal($params, 'scene_type');
        $idAry = $this->getChannelIdList($type);
        if ($idAry) {
            $params['channel_id'] = $idAry;
        }
        $count = $this->repository->getDetailListCount($params);
        if (!$count) {
            return ['total' => 0, 'rows' => []];
        }
        $list = $this->repository->getDetailList($params);
        $list = $this->getExtFields($list);
        return ['total' => $count, 'rows' => $list];
    }

    /**
     * 获取额外字段
     * @param $list
     * @param bool $single
     * @return array|mixed
     */
    public function getExtFields($list, $single = false)
    {
        $list = $single ? [$list] : $list;
        foreach ($list as &$val) {
            $val['update_time'] = $val['update_time'] ?: $val['create_time'];
            $val['origin_key'] = explode(',', $val['key']);
            $val['key'] = $val['origin_key'] ? end($val['origin_key']) : '';
            $val['msg_type_id'] = $this->getMsgTypeInfo($val['channel_id'], $val['msg_type'], 'msg_type');
            $val['msg_type_name'] = $this->getMsgTypeInfo($val['channel_id'], $val['msg_type'], 'name');
            $val['msg_type_template'] = $this->getMsgTypeInfo($val['channel_id'], $val['msg_type'], 'template');
            $val['platform_name'] = $this->MsgPlatformService->getPlatformName($val['platform_id']);
            $val['channel_name'] = $this->MsgChannelService->getChanelName($val['channel_id']);
        }
        return $single ? $list[0] : $list;
    }

    /**
     * 获取消息类型
     * @param $channelId
     * @param $msgType
     * @param mixed $field
     * @return string
     */
    protected function getMsgTypeInfo($channelId, $msgType, $field = 'name')
    {
        $info = '';
        $params = ['id' => $msgType];
        if ($channelId == MessageConst::CHANNEL_SMS_ID) {
            $config = $this->getSmsType($params);
            $info = false === $field ? $config : getVal($config, $field);

        } elseif ($channelId == MessageConst::CHANNEL_DINGTALK_ID) {
            $config = $this->getDingTalkType($params);
            $info = false === $field ? $config : getVal($config, $field);
        }
        return $info;
    }

    /**
     * 更新信息
     * @param $params
     * @return array|bool
     */
    public function updateSceneInfo($params)
    {
        $id = getVal($params, 'scene_id', 0);
        $info = [];
        if ($id) {
            $info = $this->getSceneInfo($id);
            if (isset($info['code'])) {
                return $info;
            }
        }
        $data = [];
        if (isset($params['scene_name'])) {
            $data['name'] = $params['scene_name'];
        }
        if (isset($params['msg_type'])) {
            $data['msg_type'] = $params['msg_type'];
        }
        if (isset($params['status'])) {
            $data['status'] = $params['status'];
        }
        if (isset($params['body'])) {
            $data['body'] = $params['body'];
        }
        if (isset($params['scene_key'])) {
            $data['key'] = $params['scene_key'];
        }
        if (isset($params['channel_id'])) {
            $data['channel_id'] = $params['channel_id'];
        }
        if (isset($params['platform_id'])) {
            $data['platform_id'] = $params['platform_id'];
        }
        if (array_key_exists('remark', $params)) {
            $data['remark'] = $params['remark'] ?: '';
        }
        if (isset($params['refresh_key'])) {
            // 保留最新的三个版本
            if (!$info) {
                return $this->error(lang('Empty Record'), '80223', $params);
            }
            $originKey = explode(',', $info['key']) ?: [$info['key']];
            if (count($originKey) >= 3) {
                $count = count($originKey);
                $tmp = [$originKey[$count - 2], $originKey[$count -1]];
                $originKey = array_merge($tmp);
            }
            $key = $this->generateKey();
            $key = array_merge($originKey, [$key]);
            $data['key'] = implode(',', $key);
        }
        if (!$id) {
            $data['key'] = $this->generateKey();
            $res = $this->repository->add($data);
        } else {
            $data['update_time'] = time();
            $res = $this->repository->updateInfoById($id, $data);
        }
        if (false === $res) {
            return $this->error(lang('SQL Error'), '80110');
        }
        return $res;
    }

    /**
     * 生成 key 规则
     * @return string
     */
    protected function generateKey()
    {
        return 'MC' . IdBuilder::getRandomStr(24);
    }

    /**
     * get dingtalk type list
     * @param $params
     * @return array
     */
    public function getDingTalkType($params = [])
    {
        return $this->getUnionType(
            MessageConfigConst::MSG_CONFIG_KEY_DINGTALK_TYPE,
            DingTalkConst::DINGTALK_TEMPLATE_LIST,
            '钉钉消息类型',
            $params
        );
    }

    /**
     * get sms type list
     * @param $params
     * @return array
     */
    public function getSmsType($params = [])
    {
        return $this->getUnionType(
            MessageConfigConst::MSG_CONFIG_KEY_SMS_TYPE,
            SmsConst::SMS_TEMPLATE_LIST,
            '短信消息类型',
            $params
        );
    }

    /**
     * get union type
     * @param $type
     * @param $list
     * @param $remark
     * @param $params
     * @return array|bool|mixed
     */
    public function getUnionType($type, $list, $remark, $params)
    {
        $config = $this->MsgConfigService->getConfig($type);
        $config = json_decode($config, true) ?: [];
        if (empty($config)) {
            $config = [];
            foreach ($list as $key => $val) {
                $config[] = $val;
            }
            // add config
            repository()->MsgConfigRepository->insert([
                'item' => $type,
                'value' => json_encode($config, JSON_UNESCAPED_UNICODE),
                'remark' => $remark
            ]);
        }
        if (!empty($params['id'])) {
            $search = [];
            foreach ($config as $key => $val) {
                if ($val['id'] == $params['id']) {
                    $search = $val;
                    break;
                }
            }
            return $search;
        }
        if (!empty($params['msg_type'])) {
            $search = [];
            foreach ($config as $key => $val) {
                if ($val['msg_type'] == $params['msg_type']) {
                    $search = $val;
                    break;
                }
            }
            return $search;
        }
        if (false === getVal($params, 'full', false)) {
            $conf = [];
            foreach ($config as $val) {
                $conf[] = [
                    'id' => $val['id'],
                    'name' => $val['name']
                ];
            }
            return $conf;
        }
        return $config;
    }

    /**
     * get type list
     * @param $type
     * @return array
     */
    public function getTypeList($type = '')
    {
        $channelList = $this->MsgChannelService->getChannelList();
        $platformList = $this->MsgPlatformService->getPlatformList();
        if ('dingtalk' === $type) {
            $msgType = $this->getDingTalkType();
        } elseif ('sms' === $type) {
            $msgType = $this->getSmsType();
        } else {
            $msgType = [];
        }
        return ['channel' => $channelList, 'platform' => $platformList, 'msg_type' => $msgType];
    }

    /**
     * 获取队列信息
     * @param $params
     * @return array
     */
    public function getQueueInfo($params)
    {
        // @todo get queue info
        $info = [
            'queue_name' => 'message_push_list',
            'queue_exchange' => 'message_center',
            'queue_status' => 'running...',
            'queue_backhand' => config('rabbitmq.default.http_url') ?: '暂未开放',
        ];
        return $info;
    }

    /**
     * 重启队列
     * @param $params
     * @return array
     */
    public function queueReload($params)
    {
        return RabbitMQService::reloadMq();
    }

    /**
     * 获取系统信息
     * @param $params
     * @return array
     */
    public function getSystemInfo($params)
    {
        $typeList = $this->getTypeList();
        $info = [
            'system_name' => '消息推送中心',
            'system_status' => '运行中',
            'system_version' => 'v2.0.1',
            'platform' => getVal($typeList, 'platform', []),
            'channel' => getVal($typeList, 'channel', []),
            'dingtalk_type' => $this->getDingTalkType(),
            'sms_type' => $this->getSmsType(),
        ];
        return $info;
    }

    /**
     * 获取场景值
     * [!] 不存在则插入
     * @param $scene
     * @param $platform
     * @param $channelId
     * @return mixed
     */
    public function getScene($scene, $platform, $channelId)
    {
        $platformId = $this->MsgPlatformService->getPlatformId($platform);
        $info = $this->repository->getIdByNameAndPlatformIdAndChannelId($scene, $platformId, $channelId);
        if (empty($info)) {
            $info = $this->repository->add([
                'name' => $scene,
                'platform_id' => $platformId,
                'channel_id' => $channelId,
                'status' => MessageConst::STATUS_ENABLE,
                'remark' => lang('Add by api'),
            ]);
            if (intval($info) < 1) {
                return $this->throwError(lang('Save failed'), ExceptionCodeConst::SERVER_FAIL);
            }
        }
        return ['platform_id' => $platformId, 'scene_id' => $info];
    }

    /**
     * 获取场景名
     * @param $id
     * @return string
     */
    public function getSceneName($id)
    {
        return $this->repository->getNameById($id);
    }

    /**
     * get channel id list
     * @param $type
     * @return array
     */
    protected function getChannelIdList($type)
    {
        if ('dingtalk' === $type) {
            $channelIdList = [MessageConst::CHANNEL_DINGTALK_ID];
        } elseif ('sms' === $type) {
            $channelIdList = [MessageConst::CHANNEL_SMS_ID];
        } else {
            $channelIdList = [];
        }
        return $channelIdList;
    }

}